using System;
using System.Collections.Generic;
using UnityEngine;

namespace GameCore
{
    public class EventData
    {
        
    }
    
    public interface ITopic<T> where T : EventData
    {
        public int SubscriberCount { get; }
        public EventSubscription Subscribe(Action<T> handler);
        public void RaiseEvent(T message);
    }

    public class SimpleTopic<T> : ITopic<T> where T : EventData
    {
        private readonly List<Action<T>> handlers = new();
        
        public int SubscriberCount => handlers.Count;
        
        public EventSubscription Subscribe(Action<T> handler)
        {
            handlers.Add(handler);
            return new EventSubscription(() => handlers.Remove(handler));
        }

        public void RaiseEvent(T eventData)
        {
            foreach (var handler in handlers)
                handler?.Invoke(eventData);
        }
    }

    public class EventSubscription : IDisposable
    {
        private readonly Action dispose;
        public EventSubscription(Action dispose) => this.dispose = dispose;
        public void Dispose() { dispose?.Invoke(); }
    }
    
    public class EventCenter
    {
        private readonly Dictionary<Type, object> topics = new();

        public void AddTopic<T>(ITopic<T> topic = null) where T : EventData
        {
            topics.Add(typeof(T), topic ?? new SimpleTopic<T>());
        }

        public EventSubscription SubscribeEvent<T>(Action<T> handler) where T : EventData
        {
            return topics.TryGetValue(typeof(T), out var topic) ? ((ITopic<T>)topic).Subscribe(handler) : null;
        }

        public void RaiseEvent<T>(T eventData) where T : EventData
        {
            if (topics.TryGetValue(typeof(T), out var topic))
                ((ITopic<T>)topic).RaiseEvent(eventData);
        }
    }
}